"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 数据库系统
Case Name   : 双机时，在数据库进行日志传输时，备机断电，备机操作被中断，恢复后双机关系可建立，操作可以继续
Create At   : 2020-7-7
Owner       : @peilinqian
Description :
    1. 建表
    2. 主机进行持续插入操作
    3. 备机reboot
    4. 备机reboot后，等待备机同步
    5. 主备数据一致性校验
Expect      :
    1. 建表，建表成功
    2. 主机进行持续插入操作，成功
    3. 备机reboot，成功
    4. 备机reboot后，等待备机同步，同步成功
    5. 主备数据一致性校验，主备数据一致
History     :
    Modified by @peilinqian at 2024.1.18 优化用例及日志打印
"""

import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class MyTest(unittest.TestCase):
    primary_sh = CommonSH('PrimaryDbUser')
    standby1_sh = CommonSH('Standby1DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(f"-----{os.path.basename(__file__)} start-----")
        self.pri_dbuser = Node(node='PrimaryDbUser')
        self.sta_1_root = Node(node='Standby1Root')
        self.sta_1_dbuser = Node(node='Standby1DbUser')
        self.sta_2_dbuser = Node(node='Standby2DbUser')
        self.com = Common()
        self.constant = Constant()
        self.tb_name = "t_dbsys_022"

    def test_main(self):
        text = '-----step1:建表; expect:建表成功-----'
        self.log.info(text)
        create_cmd = f'drop table if exists {self.tb_name};' \
            f'create table {self.tb_name}(id int,name varchar(20));'
        self.log.info(create_cmd)
        create_result = self.primary_sh.executDbSql(create_cmd)
        self.log.info(create_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS,
                      create_result, '执行失败:' + text)

        text = '-----step2:主机进行持续插入操作; expect:建表成功-----'
        self.log.info(text)
        insert_cmd = f"select current_time;insert into {self.tb_name} " \
            f"values(1,'testaaaaaaaaaa');"
        insert_thread = ComThread(self.primary_sh.cycle_exec_sql,
                                  args=(insert_cmd, 100,))
        insert_thread.setDaemon(True)
        insert_thread.start()

        time.sleep(5)

        self.log.info('-----step3:备机reboot; expect:reboot成功-----')
        reboot_cmd = 'reboot'
        self.sta_1_root.sh(reboot_cmd)
        i = 1
        while True:
            time.sleep(5)
            try:
                sta1_node_new = Node(node='Standby1DbUser')
                res = sta1_node_new.sh('hostname -I; who;').result().strip()
            except Exception as e:
                self.log.info(f'第{i}次失败')
                self.log.info(e)
                i += 1
            else:
                self.log.info(res)
                self.primary_sh.getDbClusterStatus('status')
                self.primary_sh.startDbCluster()
                break

        self.log.info('-----断言步骤2执行结果-----')
        insert_thread.join(600)
        insert_result = insert_thread.get_result()
        self.log.info(insert_result)
        self.assertTrue(insert_result, '执行失败:' + text)

        text = '-----step4:备机reboot后，等待备机同步; expect:同步成功-----'
        self.log.info(text)
        self.log.info('校验备机是否完成数据同步')
        flag = self.standby1_sh.check_data_consistency()
        self.assertTrue(flag, '执行失败:' + text)

        text = '-----step5:主备数据一致性校验; expect:主备数据一致-----'
        self.log.info(text)
        select_cmd = f'select count(*) from  {self.tb_name};'
        nodes_tuple = (self.pri_dbuser, self.sta_1_dbuser,
                       self.sta_2_dbuser)
        flag = self.com.check_data_sample_by_all(select_cmd, *nodes_tuple)
        self.assertTrue(flag, '执行失败:' + text)

    def tearDown(self):
        self.log.info('----this is tearDown----')
        text = '-----清除测试数据; expect:清理成功-----'
        self.log.info(text)
        drop_sql = f'drop table {self.tb_name};'
        self.log.info(drop_sql)
        msg = self.primary_sh.executDbSql(drop_sql)
        self.log.info(msg)
        self.log.info(f"-----{os.path.basename(__file__)} end-----")
        self.assertTrue('DROP TABLE' in msg)
